package handlers

import (
	"net/http"
	"time"

	"things_iot_backend/auth"
	"things_iot_backend/cache"
	"things_iot_backend/models"
	"things_iot_backend/mqtt"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"gorm.io/gorm"
)

type CommandHandler struct {
	db *gorm.DB
}

func NewCommandHandler(db *gorm.DB) *CommandHandler {
	return &CommandHandler{db: db}
}

// SendCommand 下发设备命令
func (h *CommandHandler) SendCommand(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权向该设备发送命令",
			"data":    nil,
		})
		return
	}

	var req models.CommandRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"data":    nil,
		})
		return
	}

	// 生成命令ID
	commandID := uuid.New().String()

	// 构建命令负载
	command := models.MQTTCommandPayload{
		CommandID:  commandID,
		Timestamp:  time.Now().Format(time.RFC3339),
		Command:    req.Command,
		Target:     "self", // 默认目标为设备自身
		Parameters: req.Parameters,
	}

	// 检查设备是否在线
	if device.Status != "online" {
		// 设备离线，将命令加入队列
		commandData := map[string]interface{}{
			"command_id": commandID,
			"command":    req.Command,
			"parameters": req.Parameters,
			"timestamp":  time.Now(),
		}

		if err := cache.PushCommandToQueue(device.ID, commandData); err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{
				"code":    500,
				"message": "设备离线，命令入队失败",
				"data":    nil,
			})
			return
		}

		c.JSON(http.StatusOK, gin.H{
			"code":    200,
			"message": "设备离线，命令已加入队列",
			"data": map[string]interface{}{
				"command_id": commandID,
				"status":     "queued",
			},
		})
		return
	}

	// 设备在线，直接下发命令
	if err := mqtt.PublishCommand(device, command); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "命令下发失败",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "命令下发成功",
		"data": map[string]interface{}{
			"command_id": commandID,
			"status":     "sent",
		},
	})
}

// GetQueuedCommands 获取设备队列中的命令
func (h *CommandHandler) GetQueuedCommands(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权访问该设备命令队列",
			"data":    nil,
		})
		return
	}

	// 获取队列中的命令
	commands, err := cache.GetCommandsFromQueue(device.ID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "获取命令队列失败",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "success",
		"data": map[string]interface{}{
			"commands": commands,
			"count":    len(commands),
		},
	})
}

// ClearQueuedCommands 清空设备命令队列
func (h *CommandHandler) ClearQueuedCommands(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权清空该设备命令队列",
			"data":    nil,
		})
		return
	}

	// 清空命令队列
	if err := cache.ClearCommandQueue(device.ID); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "清空命令队列失败",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "命令队列已清空",
		"data":    nil,
	})
}

// SendCommandToSubdevice 向子设备发送命令（网关设备）
func (h *CommandHandler) SendCommandToSubdevice(c *gin.Context) {
	claims, exists := c.Get("claims")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{
			"code":    401,
			"message": "未授权",
			"data":    nil,
		})
		return
	}

	userClaims := claims.(*auth.Claims)

	deviceID := c.Param("device_id")
	subdeviceID := c.Param("subdevice_id")

	var device models.Device
	if err := h.db.Where("device_id = ?", deviceID).First(&device).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{
			"code":    404,
			"message": "设备不存在",
			"data":    nil,
		})
		return
	}

	// 检查权限
	if !auth.CanAccessDevice(userClaims, device.UserID) {
		c.JSON(http.StatusForbidden, gin.H{
			"code":    403,
			"message": "无权向该设备发送命令",
			"data":    nil,
		})
		return
	}

	// 检查设备是否为网关
	if device.DeviceType != "gateway" {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "该设备不是网关设备",
			"data":    nil,
		})
		return
	}

	var req models.CommandRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "请求参数错误",
			"data":    nil,
		})
		return
	}

	// 生成命令ID
	commandID := uuid.New().String()

	// 构建命令负载（目标为子设备）
	command := models.MQTTCommandPayload{
		CommandID:  commandID,
		Timestamp:  time.Now().Format(time.RFC3339),
		Command:    req.Command,
		Target:     subdeviceID,
		Parameters: req.Parameters,
	}

	// 检查设备是否在线
	if device.Status != "online" {
		c.JSON(http.StatusBadRequest, gin.H{
			"code":    400,
			"message": "网关设备离线，无法发送命令",
			"data":    nil,
		})
		return
	}

	// 下发命令到网关
	if err := mqtt.PublishCommand(device, command); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"code":    500,
			"message": "命令下发失败",
			"data":    nil,
		})
		return
	}

	c.JSON(http.StatusOK, gin.H{
		"code":    200,
		"message": "命令下发成功",
		"data": map[string]interface{}{
			"command_id":   commandID,
			"subdevice_id": subdeviceID,
			"status":       "sent",
		},
	})
}
